/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.overall;

import com.inspur.edp.caf.generator.compileunit.CompileUnitGeneratorContext;
import com.inspur.edp.caf.generator.composite.CompositeGeneratorContext;
import com.inspur.edp.caf.generator.module.ModuleGenerator;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.gencommon.MediateType;
import com.inspur.edp.cef.generator.DotNetToJavaStringHelper;
import com.inspur.edp.cef.generator.apiGenerator.CefApiGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.CefCoreGeneratorContext;
import com.inspur.edp.cef.generator.entityGenerator.BaseEntityGenerator;
import com.inspur.edp.cef.generator.entityGenerator.BaseEntityGeneratorContext;
import com.inspur.edp.jittojava.context.JitContext;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.util.HashMap;

public abstract class CefGeneratorContext extends CompositeGeneratorContext implements ICefGeneratorContext {
    //region Bff部分集成Cef
    protected CefGeneratorContext(String metadataPath) {
        this();
        setMetadataPath(metadataPath);
    }
    //endregion

    protected CefGeneratorContext() {
        setEntityInterfaceTypes(new HashMap<String, MediateType>());
        setEntityAllInterfaceTypes(new HashMap<String, MediateType>());
        dataInterfaceTypes = new HashMap<String, MediateType>();
        nodeConstTypes = new HashMap<String, MediateType>();
    }

    private HashMap<String, MediateType> elementAssociationTypes = new HashMap<String, MediateType>();

    public final HashMap<String, MediateType> getElementAssociationTypes() {
        return elementAssociationTypes;
    }

    private HashMap<String, MediateType> elementEnumTypes = new HashMap<String, MediateType>();

    public final HashMap<String, MediateType> getElementEnumTypes() {
        return elementEnumTypes;
    }


    private String apiPackageName;

    public final String getProjectApiPackageName() {
        return apiPackageName;
    }

    public final void setProjectApiPackageName(String value) {
        apiPackageName = value;
    }

    public abstract IGspCommonDataType getCommonDataType();

    public abstract String getDataTypeNamespace();

    public abstract String getGeneratePath();

    private GspMetadata metadata;

    public final GspMetadata getMetadata() {
        return metadata;
    }

    public final void setMetadata(GspMetadata value) {
        metadata = value;
    }

    private String varConfigAttrStr;

    public final String getVarConfigAttrStr() {
        return varConfigAttrStr;
    }

    public final void setVarConfigAttrStr(String value) {
        varConfigAttrStr = value;
    }

    private String mgrAssemblyName;

    public final String getMgrAssemblyName() {
        return mgrAssemblyName;
    }

    public final void setMgrAssemblyName(String value) {
        mgrAssemblyName = value;
    }

    private MediateType privateMgrImplType;

    public final MediateType getMgrImplType() {
        return privateMgrImplType;
    }

    public final void setMgrImplType(MediateType value) {
        privateMgrImplType = value;
    }

    //todo:-wj
    private MediateType mgrInterfaceType;

    public final MediateType getMgrInterfaceType() {
        return mgrInterfaceType;
    }

    public final void setMgrInterfaceType(MediateType value) {
        mgrInterfaceType = value;
    }

    private MediateType mgrAllInterfaceType;

    public final MediateType getMgrAllInterfaceType() {
        return mgrAllInterfaceType;
    }

    public final void setMgrAllInterfaceType(MediateType value) {
        mgrAllInterfaceType = value;
    }

    private MediateType rootEntityInterfaceType;

    public final MediateType getRootEntityInterfaceType() {
        return rootEntityInterfaceType;
    }

    public final void setRootEntityInterfaceType(MediateType value) {
        rootEntityInterfaceType = value;
    }

    private MediateType rootEntityAllInterfaceType;

    public final MediateType getRootEntityAllInterfaceType() {
        return rootEntityAllInterfaceType;
    }

    public final void setRootEntityAllInterfaceType(MediateType value) {
        rootEntityAllInterfaceType = value;
    }

    private HashMap<String, MediateType> entityInterfaceTypes;

    public final HashMap<String, MediateType> getEntityInterfaceTypes() {
        return entityInterfaceTypes;
    }

    public final void setEntityInterfaceTypes(HashMap<String, MediateType> value) {
        entityInterfaceTypes = value;
    }

    private HashMap<String, MediateType> entityAllInterfaceTypes;

    public final HashMap<String, MediateType> getEntityAllInterfaceTypes() {
        return entityAllInterfaceTypes;
    }

    public final void setEntityAllInterfaceTypes(HashMap<String, MediateType> value) {
        entityAllInterfaceTypes = value;
    }

    private MediateType rootDataInterfaceType;

    public final MediateType getRootDataInterfaceType() {
        return rootDataInterfaceType;
    }

    public final void setRootDataInterfaceType(MediateType value) {
        rootDataInterfaceType = value;
    }

    private String rootNodeCode;

    public final String getRootNodeCode() {
        return rootNodeCode;
    }

    public final void setRootNodeCode(String value) {
        rootNodeCode = value;
    }

    //public Dictionary<string, Type> DataInterfaceTypes { get; }

    //public Dictionary<string, Type> NodeConstTypes { get; }
    private HashMap<String, MediateType> dataInterfaceTypes;

    public final HashMap<String, MediateType> getDataInterfaceTypes() {
        return dataInterfaceTypes;
    }

    private HashMap<String, MediateType> nodeConstTypes;

    public final HashMap<String, MediateType> getNodeConstTypes() {
        return nodeConstTypes;
    }

    private String metadataPath;

    public final String getMetadataPath() {
        return metadataPath;
    }

    public final void setMetadataPath(String value) {
        metadataPath = value;
    }

    private boolean preGenerating;

    public final boolean getPreGenerating() {
        return preGenerating;
    }

    public final void setPreGenerating(boolean value) {
        preGenerating = value;
    }

    private MediateType rootRepositoryType;

    public final MediateType getRootRepositoryType() {
        return rootRepositoryType;
    }

    public final void setRootRepositoryType(MediateType value) {
        rootRepositoryType = value;
    }
    //public Assembly RepopsitoryAssembly { get; internal set; }
    //public Type RepoAssemblerType { get; internal set; }

    /**
     * 工程级Api/Core生成器
     */
    private ModuleGenerator refModuleGenerator;

    public final ModuleGenerator getRefProjectGenerator() {
        return refModuleGenerator;
    }

    public final void setRefProjectGenerator(ModuleGenerator value) {
        refModuleGenerator = value;
    }


    // region AssemblyLoader
//    private java.util.HashMap<String, Assembly> loadedAssembly = new java.util.HashMap<String, Assembly>();

//    private String getBinPath() {
//        return Path.combine(PathTransform.GetUserProjectsRoot(), metadataService.getRefPath(getMetadataPath()));
//    }

    private JitContext jitContext;

    public final JitContext getMetadataJitContext() {
        return jitContext;
    }

    public final void setMetadataJitContext(JitContext value) {
        jitContext = value;
    }

    // endregion


    // region MetadataCache
    private final Object mdPoolLock = new Object();

//    private MetadataService metadataService=BeanUtil.getAppCtx().getBean(MetadataService.class);
    private MetadataService metadataService= SpringBeanUtils.getBean(MetadataService.class);

//    private MetadataService getMetadataService() {
//        return (metadataService != null) ? metadataService : (metadataService = ServiceManager.<MetadataService>GetService());
//    }

//    private RefCommonService lcmDtService= BeanUtil.getAppCtx().getBean(RefCommonService.class);
    private RefCommonService lcmDtService= SpringBeanUtils.getBean(RefCommonService.class);
//    private RefCommonService getLcmDtService() {
//        return (lcmDtService != null) ? lcmDtService : (lcmDtService = ServiceManager.<RefCommonService>GetService());
//    }

    // region ICefGeneratorContext Impl
    private CompileUnitGeneratorContext apiGenContext;

    public final CompileUnitGeneratorContext getApiGenContext() {
        return apiGenContext;
    }

    public final void setApiGenContext(CompileUnitGeneratorContext value) {
        apiGenContext = value;
    }

    private BaseEntityGeneratorContext entityGenContext;

    public final BaseEntityGeneratorContext getEntityGenContext() {
        return entityGenContext;
    }

    public final void setEntityGenContext(BaseEntityGeneratorContext value) {
        entityGenContext = value;
    }

    private CompileUnitGeneratorContext coreGenContext;

    public final CompileUnitGeneratorContext getCoreGenContext() {
        return coreGenContext;
    }

    private CefCoreGeneratorContext privateCoreGenCtx;
    public CefCoreGeneratorContext getCefCoreGenCtx(){return privateCoreGenCtx;}
    public  void setCefCoreGenCtx(CefCoreGeneratorContext value){privateCoreGenCtx=value;}

    public final void setCoreGenContext(CompileUnitGeneratorContext value) {
        coreGenContext = value;
    }

    private CompileUnitGeneratorContext repoGenContext;

    public final CompileUnitGeneratorContext getRepoGenContext() {
        return repoGenContext;
    }

    public final void setRepoGenContext(CompileUnitGeneratorContext value) {
        repoGenContext = value;
    }
    // endregion


    //key是元数据id, 如果要求包名改成包名+id
    private final HashMap<MetaKey, GspMetadata> metadataPools = new java.util.HashMap<MetaKey, GspMetadata>();


    public <T> T getMetadataContent(String packageName, String id)  {
        return (T) getMetadata(packageName, id).getContent();
    }

    public final GspMetadata getMetadata(String packageName, String id) {
        if (DotNetToJavaStringHelper.isNullOrEmpty(packageName)) {
            packageName = null;
        }
        MetaKey key = new MetaKey(id, packageName);
        synchronized (mdPoolLock) {
            GspMetadata metadata = null;

            if (!metadataPools.containsKey(key))
            {
                metadata=getMetadataJitContext().getMetadata(id);
                //metadata = lcmDtService.getRefMetadata(id);
                metadataPools.put(key, metadata);
            }else
                metadata = metadataPools.get(key);
            return metadata;
        }
    }

    private final static class MetaKey {
        public MetaKey(String id, String packageName) {
            this.setId(id);
            this.setPackageName(packageName);
        }

        private String id;

        public String getId() {
            return id;
        }

        public void setId(String value) {
            id = value;
        }

        private String packageName;

        public String getPackageName() {
            return packageName;
        }

        public void setPackageName(String value) {
            packageName = value;
        }
    }

    private CefApiGenerator apiGenerator;

    public final CefApiGenerator getApiGenerator() {
        return apiGenerator;
    }

    public final void setApiGenerator(CefApiGenerator value) {
        apiGenerator = value;
    }

    private BaseEntityGenerator entityGenerator;

    public final BaseEntityGenerator getEntityGenerator() {
        return entityGenerator;
    }

    public final void setEntityGenerator(BaseEntityGenerator value) {
        entityGenerator = value;
    }


    //region InitApiTypeInfos
    public final void initApiTypeInfos() {
        getApiGenerator().setCefGenCtxApiTypes();
        try {
            getEntityGenerator().setCefContextEntityTypes();
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    //endregion

    /**
     * 是否开启国际化时区，vo中复写
     * @return
     */
    public Boolean getEnableStdDateTime(){
        return false;
    }
    //endregion

    private HashMap<String, MediateType> entityResourceInfos = new HashMap<>();

    public final HashMap<String, MediateType> getEntityResourceInfos() {
        return entityResourceInfos;
    }
}
